<template>
  <div class="camera-tree-view">
    <div v-if="showHeader" class="search-bar">
      <div class="search-actions">
        <el-input v-model="searchText" placeholder="搜索摄像头" size="small" clearable style="flex: 1; margin-right: 8px" @change="handleSearch" @clear="handleSearch">
          <template #prefix>
            <el-icon>
              <Search />
            </el-icon>
          </template>
          <template #append>
            <el-button size="small" type="primary" @click="handleSearch">
              <el-icon>
                <Search />
              </el-icon>
            </el-button>
          </template>
        </el-input>
        <el-button size="small" @click="refreshAllDevices">
          <el-icon>
            <Refresh />
          </el-icon>
        </el-button>
      </div>
    </div>

    <div class="tree-content">
      <el-auto-resizer>
        <template #default="{ height, width }">
          <el-tree-v2 ref="treeRef" :data="filteredTreeData" :props="treeProps" :filter-node-method="filterNode"
            :expand-on-click-node="true" node-key="id" :default-expanded-keys="props.defaultExpandedKeys.length > 0 ? props.defaultExpandedKeys : defaultExpandedKeys" :height="height"
            :width="width" :highlight-current="true" perf-mode :item-size="48" @node-click="handleNodeClick"
            @node-contextmenu="handleNodeContextmenu">
              <template #default="{ node, data }">
                <div class="tree-node" 
                  :class="{ 
                    'is-camera': data.type === 'camera', 
                    'is-folder': data.type === 'folder',
                    'no-drag': data.type === 'camera' && !enableDrag && !showDragTip
                  }"
                  :draggable="data.type === 'camera' && enableDrag"
                  @dragstart="enableDrag ? handleDragStart($event, data) : null">
                  <!-- 文件夹节点布局 -->
                  <template v-if="data.type === 'folder'">
                    <div class="node-icon">
                      <el-icon>
                        <Folder v-if="!node.expanded" />
                        <FolderOpened v-else />
                      </el-icon>
                    </div>
                    <div class="node-content">
                      <span class="node-label">{{ data.name }}</span>
                    </div>
                  </template>

                  <!-- 摄像头节点布局 -->
                  <template v-else-if="data.type === 'camera'">
                    <!-- 复选框 -->
                    <el-checkbox 
                      v-if="showCheckboxes"
                      :model-value="selectedCameras.includes(data.id)"
                      @change="handleCameraCheckboxChange(data)"
                      class="camera-checkbox"
                      @click.stop
                    />
                    
                    <div class="camera-icon-section">
                      <el-icon :color="getCameraStatusColor(data.status)" class="camera-icon">
                        <VideoCamera />
                      </el-icon>
                      <!-- 地图标记图标放在摄像头图标下面 -->
                      <span v-if="data.hasMapMarker" class="map-marker-icon" title="已在地图标记">
                        <svg viewBox="0 0 1024 1024" width="12" height="12" fill="#1296db">
                          <path
                            d="M512 85.333333c-164.949333 0-298.666667 133.738667-298.666667 298.666667 0 164.949333 298.666667 554.666667 298.666667 554.666667s298.666667-389.717333 298.666667-554.666667c0-164.928-133.717333-298.666667-298.666667-298.666667z m0 448a149.333333 149.333333 0 1 1 0-298.666666 149.333333 149.333333 0 0 1 0 298.666666z">
                          </path>
                        </svg>
                      </span>
                    </div>
                    
                    <div class="camera-content">
                      <div class="camera-header">
                        <el-tooltip :content="data.name" placement="top">
                          <span class="camera-name">{{ data.name }}</span>
                        </el-tooltip>
                        <div v-if="enableDrag" class="tcamera-acions">
                          <el-tooltip content="拖拽到右侧视频区域播放" placement="top">
                            <el-icon class="drag-hint">
                              <Rank />
                            </el-icon>
                          </el-tooltip>
                          <el-button size="small" text @click.stop="controlPTZ(data)" :disabled="data.status !== 'online' || !data.ptzEnable"
                            title="云台控制" class="ptz-btn">
                            <el-icon>
                              <SetUp />
                            </el-icon>
                          </el-button>
                        </div>
                      </div>
                      
                      <div class="camera-footer">
                        <div class="footer-left">
                          <span class="camera-ip">{{ data.ip }}</span>
                        </div>
                        <span v-if="data.status === 'online' && showDragTip" class="drag-tip">拖拽播放</span>
                      </div>
                    </div>
                  </template>
                </div>
              </template>
          </el-tree-v2>
        </template>

      </el-auto-resizer>

    </div>

    <!-- 右键菜单 -->
    <el-dropdown ref="contextMenuRef" :virtual-ref="contextMenuVirtualRef" :virtual-triggering="true"
      trigger="contextmenu" placement="bottom-start">
      <template #dropdown>
        <el-dropdown-menu>
          <el-dropdown-item v-if="contextMenuData?.type === 'camera'" @click="controlPTZ(contextMenuData)"
            :disabled="contextMenuData?.status !== 'online' || !contextMenuData?.ptzEnable">
            <el-icon>
              <SetUp />
            </el-icon>
            云台控制
          </el-dropdown-item>
          <el-dropdown-item v-if="contextMenuData?.type === 'camera'" @click="viewCameraInfo(contextMenuData)">
            <el-icon>
              <InfoFilled />
            </el-icon>
            查看详情
          </el-dropdown-item>
          <el-dropdown-item v-if="contextMenuData?.type === 'folder'" @click="refreshFolder(contextMenuData)">
            <el-icon>
              <Refresh />
            </el-icon>
            刷新目录
          </el-dropdown-item>
        </el-dropdown-menu>
      </template>
    </el-dropdown>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted } from 'vue'
import {
  ElTreeV2,
  ElAutoResizer,
  ElInput,
  ElButton,
  ElIcon,
  ElDropdown,
  ElDropdownMenu,
  ElDropdownItem
} from 'element-plus'
import { warning, success, info } from '@/utils/toast'
import {
  FolderOpened,
  Folder,
  VideoCamera,
  SetUp,
  Search,
  Refresh,
  InfoFilled,
  Rank
} from '@element-plus/icons-vue'
import { useCameraStore } from '@/stores/camera'
import { useStreamStore } from '@/stores/stream'
import { $getDeviceListByKeyword } from '@/api/device'
import { buildSearchDevicesStreamUrls } from '@/utils/streamUrl'
import type { TreeNode } from '@/types'

// 接口定义
interface CameraTreeNode {
  id: string
  name: string
  type: 'folder' | 'camera'
  status?: 'online' | 'offline'
  ip?: string
  url?: string
  children?: CameraTreeNode[]
  parentId?: string | number
  hasMapMarker?: boolean  // 是否在地图中有标记
  nvrId?: number  // NVR ID
  subEquId?: number  // 子设备 ID
  ptzEnable?: boolean  // 是否支持云台控制
}

// Props
interface Props {
  data?: CameraTreeNode[]
  defaultExpandAll?: boolean
  showHeader?: boolean
  useStoreData?: boolean
  showDragTip?: boolean  // 是否显示拖拽提示
  enableDrag?: boolean   // 是否启用拖拽功能
  selectedCameras?: string[]  // 已选中的摄像机ID列表
  defaultExpandedKeys?: string[]  // 默认展开的节点ID列表
  showCheckboxes?: boolean  // 是否显示复选框
}

const props = withDefaults(defineProps<Props>(), {
  data: () => [],
  defaultExpandAll: true,
  showHeader: true,
  useStoreData: true,
  showDragTip: true,  // 默认显示拖拽提示
  enableDrag: true,    // 默认启用拖拽功能
  selectedCameras: () => [],  // 默认空数组
  defaultExpandedKeys: () => [],  // 默认空数组
  showCheckboxes: true  // 默认显示复选框
})

// Emits
const emit = defineEmits<{
  'control-ptz': [camera: CameraTreeNode]
  'node-click': [node: CameraTreeNode]
  'refresh': []
  'camera-checkbox-change': [camera: CameraTreeNode, checked: boolean]
}>()

// Store
const cameraStore = useCameraStore()

// 响应式数据
const treeRef = ref<InstanceType<typeof ElTreeV2>>()
const contextMenuRef = ref()
const contextMenuVirtualRef = ref()
const searchText = ref('')
const contextMenuData = ref<CameraTreeNode | null>(null)
const searchResults = ref<CameraTreeNode[]>([])
const isSearchMode = ref(false)

// 树形组件配置
const treeProps = {
  children: 'children',
  label: 'name',
  class: (data: any) => {
    return data.type === 'folder' ? 'folder-node' : 'camera-node'
  }
}

// 默认展开的节点
const defaultExpandedKeys = ref<string[]>([])

// 将TreeNode转换为CameraTreeNode格式
const convertTreeNodeToCameraTreeNode = (node: TreeNode): CameraTreeNode => {
  const cameraNode: CameraTreeNode = {
    id: String(node.id),
    name: node.name,
    type: 'folder',
    parentId: String(node.parentId),
    children: node.children?.map(convertTreeNodeToCameraTreeNode)
  }

    // 如果有设备，将设备转换为摄像头节点
    if (node.devices && node.devices.length > 0) {
      const deviceNodes: CameraTreeNode[] = node.devices.map(device => ({
        id: `device_${device.id}`,
        name: device.name,
        type: 'camera' as const,
        status: device.status === 1 ? 'online' : 'offline',
        ip: device.ip,
        url: device.flv || device.flvsub, // 优先使用flv主码流，其次FLV子码流
        parentId: String(node.id),
        hasMapMarker: !!device.mapDevice,  // 检查是否有地图设备信息
        nvrId: device.nvrId,  // 传递 NVR ID
        subEquId: device.subEquId,  // 传递子设备 ID
        ptzEnable: device.ptzEnable  // 传递云台控制支持状态
      }))

    // 将设备节点添加到子节点中
    if (cameraNode.children) {
      cameraNode.children.push(...deviceNodes)
    } else {
      cameraNode.children = deviceNodes
    }
  }

  return cameraNode
}

// 计算属性 - 获取树形数据
const treeData = computed(() => {
  if (props.useStoreData) {
    // 使用store中的真实数据
    console.log('CameraTreeView: Using store data, cameraTree:', cameraStore.cameraTree)
    const convertedData = cameraStore.cameraTree.map(convertTreeNodeToCameraTreeNode)
    console.log('CameraTreeView: Converted data:', convertedData)
    return convertedData
  } else {
    // 使用传入的props数据
    console.log('CameraTreeView: Using props data:', props.data)
    return props.data
  }
})

// 计算属性 - 过滤后的树形数据
const filteredTreeData = computed(() => {
  // 如果是搜索模式，返回搜索结果
  if (isSearchMode.value && searchText.value.trim()) {
    return searchResults.value
  }
  
  // 否则使用原有的过滤逻辑
  if (!searchText.value) return treeData.value

  const searchTerm = searchText.value.toLowerCase()
  console.log('CameraTreeView: Searching for:', searchTerm)
  console.log('CameraTreeView: Tree data:', treeData.value)

  const filterTree = (nodes: CameraTreeNode[]): CameraTreeNode[] => {
    return nodes.filter(node => {
      // 检查当前节点是否匹配搜索条件
      const nameMatch = node.name.toLowerCase().includes(searchTerm)
      const ipMatch = node.type === 'camera' && node.ip && node.ip.toLowerCase().includes(searchTerm)
      const nodeMatches = nameMatch || ipMatch

      if (nodeMatches) {
        console.log('CameraTreeView: Found match:', node.name, node.type, node.ip)
      }

      // 检查子节点是否有匹配的
      let childrenMatch = false
      if (node.children) {
        const filteredChildren = filterTree(node.children)
        if (filteredChildren.length > 0) {
          childrenMatch = true
        }
      }

      // 如果当前节点匹配或有子节点匹配，则保留该节点
      return nodeMatches || childrenMatch
    }).map(node => ({
      ...node,
      children: node.children ? filterTree(node.children) : undefined
    }))
  }

  const result = filterTree(treeData.value)
  console.log('CameraTreeView: Filtered result:', result)
  return result
})

// 方法
const filterNode = (value: string, data: any) => {
  if (!value) return true
  const searchTerm = value.toLowerCase()

  // 匹配设备名称
  const nameMatch = data.name.toLowerCase().includes(searchTerm)

  // 匹配IP地址（仅对摄像头节点）
  const ipMatch = data.type === 'camera' && data.ip && data.ip.toLowerCase().includes(searchTerm)

  return nameMatch || ipMatch
}

const getCameraStatusColor = (status?: string) => {
  return status === 'online' ? '#67c23a' : '#f56c6c'
}

const handleNodeClick = async (data: any) => {
  emit('node-click', data)

  // 如果是文件夹节点且还没有设备数据，自动加载设备
  if (data.type === 'folder' && props.useStoreData) {
    const nodeId = typeof data.id === 'string' ? parseInt(data.id) : data.id

    // 检查是否已经有设备数据，避免重复加载
    const hasDevices = data.children && data.children.some((child: any) => child.type === 'camera')
    if (!hasDevices) {
      console.log(`CameraTreeView: Auto-loading devices for folder ${nodeId} (${data.name})`)
      try {
        await cameraStore.fetchDevicesByNodeId(nodeId)
      } catch (error) {
        console.error('Auto-load devices failed:', error)
      }
    } else {
      console.log(`CameraTreeView: Folder ${nodeId} already has devices, skipping auto-load`)
    }
  }

  // 摄像头点击不再自动播放，只能通过拖拽添加
}

const handleNodeContextmenu = (evt: Event, data: any) => {
  evt.preventDefault()
  contextMenuData.value = data
  contextMenuVirtualRef.value = {
    getBoundingClientRect() {
      return {
        width: 0,
        height: 0,
        top: (evt as MouseEvent).clientY,
        left: (evt as MouseEvent).clientX,
        right: (evt as MouseEvent).clientX,
        bottom: (evt as MouseEvent).clientY,
      }
    }
  }

  nextTick(() => {
    contextMenuRef.value?.handleOpen()
  })
}


const controlPTZ = (camera: CameraTreeNode) => {
  if (camera.status !== 'online') {
    warning('摄像头离线，无法控制')
    return
  }
  if (!camera.ptzEnable) {
    warning('该摄像头不支持云台控制')
    return
  }
  emit('control-ptz', camera)
}

const viewCameraInfo = (camera: CameraTreeNode) => {
  info(`摄像头详情：${camera.name} - ${camera.ip}`)
}

const refreshTree = () => {
  emit('refresh')
  success('目录已刷新')
}

const refreshFolder = async (folder: CameraTreeNode) => {
  try {
    if (props.useStoreData && folder.type === 'folder') {
      // 文件夹节点的ID是数字类型，需要从字符串转换
      const nodeId = typeof folder.id === 'string' ? parseInt(folder.id) : folder.id
      console.log(`CameraTreeView: Refreshing folder ${nodeId} (${folder.name})`)
      await cameraStore.fetchDevicesByNodeId(nodeId)
      success(`已刷新目录：${folder.name}`)
    } else {
      success(`已刷新目录：${folder.name}`)
    }
  } catch (error) {
    console.error('Refresh folder failed:', error)
    warning('刷新目录失败')
  }
}

const refreshAllDevices = async () => {
  try {
    if (props.useStoreData) {
      console.log('CameraTreeView: Refreshing all devices in all folders')

      // 获取所有文件夹节点
      const getAllFolderNodes = (nodes: CameraTreeNode[]): CameraTreeNode[] => {
        const folders: CameraTreeNode[] = []
        nodes.forEach(node => {
          if (node.type === 'folder') {
            folders.push(node)
            if (node.children) {
              folders.push(...getAllFolderNodes(node.children))
            }
          }
        })
        return folders
      }

      const allFolders = getAllFolderNodes(treeData.value)
      console.log(`CameraTreeView: Found ${allFolders.length} folders to refresh`)

      // 并行刷新所有文件夹的设备
      const refreshPromises = allFolders.map(async (folder) => {
        const nodeId = typeof folder.id === 'string' ? parseInt(folder.id) : folder.id
        try {
          await cameraStore.fetchDevicesByNodeId(nodeId)
          console.log(`CameraTreeView: Successfully refreshed folder ${nodeId} (${folder.name})`)
        } catch (error) {
          console.error(`CameraTreeView: Failed to refresh folder ${nodeId} (${folder.name}):`, error)
          // 不抛出错误，继续刷新其他文件夹
        }
      })

      await Promise.all(refreshPromises.map(p => p.catch(() => { })))
      success(`已刷新所有目录中的设备 (${allFolders.length}个目录)`)
    } else {
      success('已刷新所有设备')
    }
  } catch (error) {
    console.error('Refresh all devices failed:', error)
    warning('刷新所有设备失败')
  }
}

// 处理搜索功能 - 调用 $getDeviceListByKeyword 接口
const handleSearch = async () => {
  if (!searchText.value.trim()) {
    // 如果搜索关键词为空，退出搜索模式
    isSearchMode.value = false
    searchResults.value = []
    return
  }

  try {
    console.log('CameraTreeView: Searching devices with keyword:', searchText.value.trim())
    
    // 获取流媒体服务器列表用于构建完整流地址
    const streamStore = useStreamStore()
    
    // 确保流媒体服务器列表已加载
    if (streamStore.streamServers.length === 0) {
      console.log('CameraTreeView: Loading stream servers before search...')
      await streamStore.loadStreamServers()
    }
    
    const response = await $getDeviceListByKeyword(searchText.value.trim())
    
    if (response.data && Array.isArray(response.data)) {
      // 使用工具函数为搜索设备构建完整的流地址
      const devicesWithStreamUrls = buildSearchDevicesStreamUrls(response.data, streamStore.streamServers)
      
      // 将搜索结果转换为 CameraTreeNode 格式，使用构建的完整流地址
      const searchNodes: CameraTreeNode[] = devicesWithStreamUrls.map(device => ({
        id: `device_${device.id}`,
        name: device.name,
        type: 'camera' as const,
        status: device.status === 1 ? 'online' : 'offline',
        ip: device.ip,
        url: device.flv || device.flvsub, // 使用构建的完整流地址
        parentId: String(device.menuId || 'root'),
        hasMapMarker: !!device.mapDevice,
        nvrId: device.nvrId,
        subEquId: device.subEquId,
        ptzEnable: device.ptzEnable
      }))
      
      searchResults.value = searchNodes
      isSearchMode.value = true
      console.log(`CameraTreeView: Found ${searchNodes.length} devices matching "${searchText.value.trim()}"`)
      console.log('CameraTreeView: Search results with stream URLs:', searchNodes)
      console.log('CameraTreeView: Available stream servers:', streamStore.streamServers)
    } else {
      searchResults.value = []
      isSearchMode.value = true
      console.log('CameraTreeView: No devices found for search keyword:', searchText.value.trim())
    }
  } catch (error) {
    console.error('CameraTreeView: Search failed:', error)
    warning('搜索设备失败，请重试')
    searchResults.value = []
    isSearchMode.value = false
  }
}

const handleDragStart = (event: DragEvent, data: CameraTreeNode) => {
  if (data.type === 'camera' && data.status === 'online') {
    const cameraData = {
      id: data.id,
      name: data.name,
      ip: data.ip,
      status: data.status,
      url: data.url,
      type: 'camera',
      nvrId: data.nvrId,
      subEquId: data.subEquId,
      ptzEnable: data.ptzEnable  // 添加云台控制支持状态
    }
    console.log('CameraTreeView: Drag start data:', cameraData)
    event.dataTransfer?.setData('text/plain', JSON.stringify(cameraData))
    event.dataTransfer!.effectAllowed = 'copy'
  } else {
    event.preventDefault()
  }
}

// 处理摄像机复选框变化
const handleCameraCheckboxChange = (camera: CameraTreeNode) => {
  const isChecked = props.selectedCameras.includes(camera.id)
  emit('camera-checkbox-change', camera, !isChecked)
}

// 保存展开状态到本地存储
const saveExpandedState = () => {
  if (treeRef.value) {
    // 使用当前展开的keys
    const expandedKeys = defaultExpandedKeys.value
    localStorage.setItem('camera-tree-expanded-keys', JSON.stringify(expandedKeys))
  }
}

// 从本地存储恢复展开状态
const restoreExpandedState = () => {
  try {
    const savedKeys = localStorage.getItem('camera-tree-expanded-keys')
    if (savedKeys) {
      const expandedKeys = JSON.parse(savedKeys)
      if (Array.isArray(expandedKeys) && expandedKeys.length > 0) {
        defaultExpandedKeys.value = expandedKeys
        console.log('CameraTreeView: Restored expanded keys from localStorage:', expandedKeys)
        return true
      }
    }
  } catch (error) {
    console.warn('CameraTreeView: Failed to restore expanded state:', error)
  }
  return false
}

// 监听搜索文本变化 - 现在使用 handleSearch 函数处理
// watch(searchText, (val) => {
//   if (treeRef.value) {
//     treeRef.value.filter(val)
//   }
// })

// 监听树形数据变化，自动展开第一个文件夹
watch(treeData, (newTreeData) => {
  if (newTreeData.length > 0 && !props.defaultExpandAll) {
    const firstFolder = newTreeData[0]
    if (firstFolder.type === 'folder') {
      // 只有在没有已展开的节点时才设置默认展开
      if (defaultExpandedKeys.value.length === 0) {
        defaultExpandedKeys.value = [String(firstFolder.id)]
        console.log('CameraTreeView: Auto-expanding first folder after data update:', firstFolder.id, firstFolder.name)
      }
    }
  }
}, { immediate: true })

// 初始化展开的节点
onMounted(() => {
  // 首先尝试从本地存储恢复展开状态
  const restored = restoreExpandedState()
  
  if (!restored) {
    // 如果没有保存的状态，则使用默认逻辑
    if (props.defaultExpandAll) {
      const getAllNodeIds = (nodes: CameraTreeNode[]): string[] => {
        const ids: string[] = []
        nodes.forEach(node => {
          if (node.type === 'folder') {
            ids.push(node.id)
            if (node.children) {
              ids.push(...getAllNodeIds(node.children))
            }
          }
        })
        return ids
      }

      defaultExpandedKeys.value = getAllNodeIds(treeData.value)
    } else {
      // 默认只展开第一个文件夹
      if (treeData.value.length > 0 && treeData.value[0].type === 'folder') {
        defaultExpandedKeys.value = [String(treeData.value[0].id)]
        console.log('CameraTreeView: Auto-expanding first folder:', treeData.value[0].id, treeData.value[0].name)
      }
    }
  }
  
  // 监听展开状态变化并保存
  nextTick(() => {
    if (treeRef.value) {
      // 监听展开状态变化
      const originalSetExpandedKeys = treeRef.value.setExpandedKeys
      treeRef.value.setExpandedKeys = function(keys: any[]) {
        originalSetExpandedKeys.call(this, keys)
        saveExpandedState()
      }
    }
  })
})
</script>

<style scoped>
.camera-tree-view {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  overflow: hidden;
}

.tree-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #ebeef5;
  background: #fafafa;
}

.tree-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.tree-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.search-bar {
  padding: 12px 16px 0;
}

.search-actions {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
}

.tree-content {
  flex: 1;
  padding: 12px;
  overflow: auto;
}

.tree-node {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 6px 8px;
  transition: all 0.3s;
  min-height: 36px;
  border-radius: 4px;
  position: relative;
}

.tree-node:hover {
  background: #f5f7fa;
}

/* Camera 节点样式已移至 el-tree-v2 的深度选择器中 */

.node-icon {
  margin-right: 8px;
  display: flex;
  align-items: center;
  font-size: 16px;
  color: #606266;
}

.node-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  width: 100%;
  justify-content: center;
}

.node-label {
  font-size: 14px;
  color: #303133;
  font-weight: 500;
  line-height: 1.4;
  word-break: keep-all;
  white-space: nowrap;
  overflow: visible;
  text-overflow: clip;
}

.camera-info {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
  flex-wrap: wrap;
  width: 100%;
}

.camera-ip {
  font-size: 12px;
  color: #909399;
  font-family: 'Courier New', monospace;
  min-width: 80px;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-right: 8px;
}

.map-marker-icon {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
}

.map-marker-icon svg {
  transition: transform 0.2s;
}

.map-marker-icon:hover svg {
  transform: scale(1.2);
}

.node-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.3s;
  margin-left: auto;
  padding-left: 4px;
  min-width: auto;
  flex-shrink: 0;
}

.tree-node:hover .node-actions {
  opacity: 1;
}

.drag-hint {
  color: #67c23a;
  font-size: 18px;
  margin-right: 2px;
  padding: 2px;
}

.drag-tip {
  font-size: 10px;
  color: #909399;
  background: #f0f0f0;
  padding: 2px 6px;
  border-radius: 3px;
  flex-shrink: 0;
  white-space: nowrap;
}

/* 文件夹节点样式 */
.tree-node.is-folder {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  height: 32px;
}

.tree-node.is-folder .node-icon {
  margin-right: 8px;
  font-size: 16px;
  color: #606266;
}

.tree-node.is-folder .node-content {
  flex: 1;
}

.tree-node.is-folder .node-label {
  font-size: 14px;
  color: #303133;
  font-weight: 500;
}

/* 摄像头节点样式 */
.tree-node.is-camera {
  display: flex;
  align-items: center;
  height: 48px;
}

.camera-checkbox {
  margin-right: 8px;
  flex-shrink: 0;
}

.camera-icon-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
  margin-right: 8px;
}

.camera-icon {
  font-size: 18px;
}

.camera-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}

.camera-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2px;
}

.camera-name {
  font-size: 14px;
  color: #303133;
  font-weight: 500;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 120px;
}

/* 当拖拽功能禁用时，允许摄像头名称显示更多内容 */
.tree-node.is-camera.no-drag .camera-name {
  max-width: 100%;
}

.status-tag {
  flex-shrink: 0;
  font-size: 11px;
  height: 18px;
  line-height: 16px;
  padding: 0 6px;
}

.camera-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
}

.footer-left {
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 0;
  max-width: calc(100% - 80px); /* 为右侧拖拽播放按钮预留空间 */
}

/* 当拖拽提示不显示时，充分利用空间 */
.tree-node.is-camera.no-drag .footer-left {
  max-width: 100%; /* 移除右侧空间限制 */
}

.camera-ip {
  color: #909399;
  font-family: 'Courier New', monospace;
  font-size: 11px;
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 110px;
}

/* 当拖拽功能禁用时，允许摄像头IP显示更多内容 */
.tree-node.is-camera.no-drag .camera-ip {
  max-width: 180px !important;
}

.map-marker-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.map-marker-icon svg {
  transition: transform 0.2s;
}

.map-marker-icon:hover svg {
  transform: scale(1.1);
}

.tcamera-acions {
  display: flex;
  align-items: center;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.3s;
  flex-shrink: 0;
}

.tree-node.is-camera:hover .tcamera-acions {
  opacity: 1;
}

.drag-hint {
  color: #67c23a;
  font-size: 16px;
  cursor: grab;
}

.drag-hint:active {
  cursor: grabbing;
}

.ptz-btn {
  padding: 2px 4px !important;
  min-width: auto !important;
  height: 20px !important;
  font-size: 12px;
}

/* 确保节点内容垂直居中 */
:deep(.el-tree-node_content) {
  display: flex;
  align-items: center;
}
</style>